Платформа .NET решает многие проблемы, которые досаждали программистам в прошлом. К их числу относятся проблемы, связанные с развертыванием приложений, управлением версиями, утечкой памяти, а также проблемы безопасности. Платформа .NET позволяет разрабатывать мощные, независимые от языка программирования, настольные приложения и масштабируемые (расширяемые) Web-службы, построенные на базе новой мощной полнофункциональной библиотеки классов .NET Framework.
Представьте себе симфонический
оркестр, в котором группам струнных
смычковых и ударных инструментов предстоит
исполнить свои партии, используя при этом
разные варианты партитуры. В таком случае,
чтобы исполнить даже простейшую
Даже если бы платформа .NET смогла
устранить все проблемы прошлого, этого все
равно было бы недостаточно. Постоянный рост
требований со стороны клиентов к
функциональным возможностям приложений
является одним из непреложных законов
программирования.
Возможность беспрепятственной
работы приложений в разных компьютерных
сетях, обусловленная развитием Internet, стала
императивом. Функциональные возможности
компонентов должны быть доступны также и с
других машин. При этом никто из
программистов не хочет писать базовый
каркас; все они жаждут писать приложения,
предназначенные для непосредственного
решения проблем своих клиентов.
Платформа .NET содержит общеязыковую среду выполнения (Common Language Runtime — CLR). Общеязыковая среда выполнения CLR поддерживает управляемое выполнение, которое характеризуется рядом преимуществ. Совместно с общей системой типов (Common Type System — CTS) общеязыковая среда выполнения CLR поддерживает возможность взаимодействия языков платформы .NET. Кроме того, платформа .NET предоставляет большую полнофункциональную библиотеку классов .NET Framework.
Чтобы решить все проблемы,
связанные с разработкой Windows-приложений,
платформа .NET должна обладать базовым
набором служб, которые в любой момент
доступны в любом языке программирования.
Чтобы предоставить такие службы, платформа
.NET должна иметь достаточно сведений о
приложении.
Сериализация (преобразование в
последовательную форму) объекта может
послужить в качестве простого примера.
Перед каждым программистом, рано или поздно,
возникает проблема сохранения данных. Но
зачем каждому программисту вновь
изобретать колесо, решая вопрос о том, как
следует сохранять вложенные объекты и
сложные структуры данных? Зачем каждому
программисту понимать, как эти объекты и
данные хранятся в разных информационных
хранилищах? Платформа .NET позволяет
выполнить сериализацию объекта без
вмешательства программиста. При желании
разработчик может это сделать и
самостоятельно.
Чтобы понять, как происходит
сериализация объектов, мы рассмотрим
относящийся к данной главе пример Serialize (Сериализация).
Не станем акцентировать внимание на
применяемых приемах программирования. Они
будут рассмотрены позже. Сейчас же мы
сосредоточимся на используемых в этом
примере понятиях.
//Serialize.cs
fusing <mscorlib.dll>
fusing <System.Runtime.Serialization.Formatters.Soap.dll>
// <Система. Время выполнения.
// Преобразование в
последовательную форму. Форматеры. Soap.dll>
using namespace System;
// использование пространства имен
Система;
using namespace System::Collections;
// использование пространства имен
Система:: Коллекции;
using namespace System::10;
// использование пространства имен
Система:: Ввод-вывод;
using namespace
System::Runtime:Serialization::Formatters::Soap; //
использование пространства имен
// Система:: Время выполнения::
Преобразование в последовательную // форму::
Форматеры:: Soap;
[Serializable]
// [Преобразование в
последовательную форму]
_gc class Customer
// класс сборщика мусора Клиент
{
public:
String *pname; // Строка long id; //
идентификатор
};
_gc class Test
// класс сборщика мусора Испытание
{
public:
static void Main()
{
ArrayList *plist = new ArrayList;
Customer *pcust = new Customer; // новый Клиент
pcust->pname = "Charles Darwin"; // Чарльз Дарвин
pcust->id = 10; // идентификатор plist->Add(pcust); //
Добавить
pcust = new Customer; // новый Клиент pcust->pname
= "Isaac Newton"; // Исаак Ньютон pcust->id =20; //
идентификатор plist->Add(pcust); // Добавить
for (int i=0; i < plist->get_Count(); i++)
{
Customer *pcust = // Клиент
dynamic_cast<Customer _gc *> // <Клиент _
сборщик
//мусора *> (plist->get_Item(i)); Console::WriteLine(
"{0}: {!}",
pcust->pname, _box(pcust->id)); //
идентификатор } ~
Console::WriteLine("Saving Customer List"); // ("Сохранение
списка клиентов"); FileStream *ps = new FileStream(
"cust.txt", FileMode::Create); // Создать
SoapFormatter *pf = new SoapFormatter; pf->Serialize(ps, plist);
// Преобразование в
последовательную форму; ps->Close ();
Console::WriteLine("Restoring to New List");
// "Восстановить в новом списке");
ps = new FileStream("cust.txt", FileMode::Open); //
Открыть
pf = new SoapFormatter();
ArrayList *plist2 =
dynamic_cast<ArrayList *>
(pf->Deserialize(ps)); ps->Close();
for (int i=0; i < plist->get_Count(); i++) {
Customer *pcust = // Клиент
dynamic_cast<Customer _gc *> // <Клиент _
сборщик мусора *>
(plist->get_Item(i)); Console::WriteLine( "{0}:
{!}",
pcust->pname, _box(pcust->id)); //
идентификатор } } };
void main(void) {
Test::Main(); }
Мы определили класс Customer (Клиент)
с двумя полями: pname и id (идентификатор).
Сначала программа создает экземпляр
коллекции, в котором будут храниться
экземпляры класса Customer (Клиент). Мы
добавляем в коллекцию два объекта Customer (Клиент),
а затем распечатываем содержимое коллекции.
Потом коллекция сохраняется на диске. Она
восстанавливается в новый экземпляр
коллекции и выводится на печать.
Распечатанные теперь данные будут
идентичны данным, которые были распечатаны
перед сохранением коллекции [В результате
инсталляции примеров программ, которыми
сопровождается данная книга, должен быть
создан пример, готовый к выполнению. Если он
отсутствует, щелкните два раза на том файле
решения Visual Studio.NET, который имеет расширение
.sin. Когда откроется Visual Studio, нажмите
комбинацию клавиш CtrI-F5 для того чтобы
построить и выполнить пример.]. Если вы
запустите приложение и откроете
получившийся в результате файл cust. txt, вы
увидите, что он содержит данные в необычном
XML-формате, который известен как простой
протокол доступа к объектам (Simple Object Access
Protocol -r- SOAP). Этот протокол специально
разработан для хранения и передачи
объектов.
Мы не писали код для того, чтобы
указать, как сохраняются или
восстанавливаются поля объекта Customer (Клиент).
Но мы определили формат (SOAP) и создали среду,
в которой затем были сохранены данные.
Классы библиотеки .NET Framework сгруппированы
таким образом, что каждый выбор — среды,
формата и способа загрузки (восстановления)
или сохранения объекта — можно сделать
независимо друг от друга. Такого типа
разделение классов существует в библиотеке
.NET Framework повсеместно.
Класс Customer (Клиент) имеет атрибут
Serializable (Преобразуемый в последовательную
форму, упорядочиваемый). Аналогично поле
имени имеет атрибут public (общедоступный).
Когда вы не хотите, чтобы объект можно было
преобразовывать в последовательную форму,
не приписывайте ему соответствующий
атрибут. Если будет предпринята попытка
сохранения объекта, который не имеет
атрибута Serializable (Преобразуемый в
последовательную форму, упорядочиваемый),
возникнет исключительная ситуация и
произойдет отказ в работе программы [Выделите
в программе атрибут Serializable (Преобразуемый в
последовательную форму, упорядочиваемый)
как комментарий и посмотрите, что при этом
произойдет. Для того чтобы ввести
комментарий в программу, вы можете
использовать синтаксис языка С и C++, то есть
применять пары символов /* и */ в качестве
открывающей и закрывающей цепочек
комментария.].
При программировании на
платформе .NET атрибуты можно применять
повсеместно. Использование атрибутов
позволяет описать способ обработки кода и
данных библиотекой классов .NET Framework. При
помощи атрибутов можно также указать
используемую модель безопасности. Атрибуты
можно использовать для того, чтобы
организовать с помощью каркаса
синхронизацию многопоточной обработки.
Благодаря использованию атрибутов
становится очевидной идея удаленного
размещения объектов.
Чтобы указать, что объект может
сохраняться и восстанавливаться
библиотекой .NET Framework, компилятор добавляет
атрибут Serializable (Преобразуемый в
последовательную форму, упорядочиваемый) к.метаданным
класса Customer (Клиент). Метаданные
представляют собой дополнительную
информацию о программном коде и данных,
которая содержится в самом .NET-приложении.
Метаданные, являющиеся характерным
свойством общеязыковой среды выполнения CLR,
могут содержать также и другую информацию о
коде, включая:
Метаданные хранятся вместе с
программным кодом, а не в каком-то
центральном хранилище наподобие
системного реестра в операционной системе
Windows. Способ их хранения не зависит от
используемого языка программирования.
Благодаря всему этому .NET-приложения
содержат самоописания. Во время выполнения
приложения может быть выдан запрос
метаданных с целью получения информации о
коде (например, о наличии или отсутствии
атрибута Serializacle (Преобразуемый в
последовательную форму, упорядочиваемый)).
Вы можете расширить метаданные, дополнив их
своими собственными атрибутами.
В нашем примере библиотека .NET
Framework может запросить метаданные для того,
чтобы получить информацию о структуре
объекта Customer (Клиент), которая затем
используется для сохранения и
восстановления объекта.
В предыдущем примере Serialize (Сериализация) используются классы SoapFor-matrer и FileStream. Они являются лишь двумя из более чем 2500 классов библиотеки .NET Framework. Классы библиотеки .NET Framework создают каркас (инфраструктуру) приложения и предоставляют системные службы .NET-приложениям. Ниже перечислены лишь некоторые из функциональных возможностей библиотеки классов .NET Framework:
библиотека базовых классов. — содержит основные функциональные возмож ности, такие как строки, массивы и элементы форматирования; передача данных посети; система безопасности; удаленная обработка; диагностика; ввод/вывод; базы данных; язык ХМ L; Web-службы, которые позволяют использовать интерфейсы компонентов в любом месте Internet; Web-программирование; пользовательский интерфейс операционной системы Windows.Предположим, что вы хотите
зашифровать ваши данные, и, следовательно,
не желаете полагаться на сериализацию (преобразование
в последовательную форму), реализованную на
основе простого протокола доступа к
объектам (Simple Object Access Protocol — SOAP), входящего в
состав библиотеки .NET Framework. Ваш класс может
наследовать интерфейс ISeriaiizaole и содержать
реализацию соответствующего алгоритма (как
это сделать, мы обсудим в следующих главах).
Тогда при сохранении и восстановлении
данных библиотека .NET Framework будет
использовать ваши методы.
Но как библиотека .NET Framework узнает
о том. что вы реализовали интерфейс 15-erializable?
Оказывается, она может запросить
метаданные соответствующего класса для
того, чтобы узнать, наследчет ли он
указанный интерфейс! Затем при
сериадизации объекта или преобразовании
его из последовательной формы в "параллельную"
библиотека классов .NET Framework может
использовать либо ее собственный алгоритм,
либо код соответствующего класса.
Программирование на основе
интерфейсов используется платформой .NET для
того, чтобы при помощи разработанных
программистом объектов дополнить
стандартные функционачьные возможности
библиотеки классов .NET Framework. Использование
интерфейсов позволяет также привести
работу с разными объектами к общему
знаменателю, не зная точного типа объекта.
Например, средства форматирования (скажем,
форматер SOAP, который используется в данном
примере) наследуют интерфейс I Formatter.
Программы могут быть написаны
безотносительно к какому бы то ни было
конкретному (двоичному, SOAP) форматеру,
используемому сейчас, или форматеру,
который будет использоваться в будущем, и
при этом они будут работать должным образом.
Если тип содержит метаданные, тогда среда выполнения может делать многие замечательные вещи. Но все ли объекты в .NET содержат метаданные? Да! Каждый тип, будь то тип, определенный пользователем (например, Customer (Клиент)) или тип, являющийся частью библиотеки классов .NET Framework (например, FileStream). является объектом среды .NET. Все объекты среды .NET являются производными от одного базового класса— системного класса Object (Объект). Поэтому все. что выполняется в среде .NET, имеет тип и, следовательно, содержит метаданные.
Типы
Типы — сердце модели программирования, основанной на общеязыковой среде выполнения
CLR. Тип аналогичен классу в большинстве объектно-ориентированных языков программирования
и сочетает в себе используемую абстракцию данных и их поведение. Тип в общеязыковой
среде выполнения CLR содержит:
поля (элементы данных);
методы;
свойства;
события.
Имеются также встроенные простые типы
данных. Например, целочисленный тип данных,
тип чисел с плавающей точкой, строки, и так
далее.
В нашем примере код
преобразования объектов в
последовательную форму может
просматривать список (типа ArrayList) объектов
Customer (Клиент), и сохранять каждый объект, а
также весь массив, к которому принадлежит
объект. Это возможно благодаря тому, что
метаданные содержат информацию как о типе
объекта, так и о его размещении.
Из дальнейшего станет ясно, что
благодаря тому, что все .NET-объекты являются
производными от общего базового класса,
открываются и некоторые другие возможности.
Типы, передаваемые библиотеке
классов .NET Framework, имеют некоторую общую
природу. Эти типы определяются обшей
системой типов (Common Type System — CTS). Общая
система типов CTS определяет правила для
типов и действий, которые поддерживает
среда выполнения CLR. Именно общая система
типов CTS накладывает на классы .NET
ограничение единичного наследования
реализации. Хотя общая система типов CTS
определена для широкого множества языков
программирования, не все эти языки должны
поддерживать все свойства типов данных,
предусмотренные в общей системе типов CTS.
Например, в языке C++ множественное
наследование разрешено для неуправляемых
классов, но запрещено для управляемых.
Промежуточный язык Microsoft (Microsoft
Intermediate Language — MSIL, или просто IL) определяет
систему команд, которая используется всеми
компиляторами, транслирующими на язык
платформы .NET. Этот промежуточный язык не
зависит от используемой платформы. Код на
языке MSIL затем преобразуется во внутренний
(собственный) код платформы. Мы можем быть
уверены, что классы библиотеки .NET Framework
будут работать со всеми языками,
поддерживаемыми платформой .NET. Особенности
создаваемого приложения больше не
накладывают ограничений на выбор языка
программирования, а выбор языка
программирования больше не ограничивает
возможности создаваемого приложения.
Промежуточный язык MSIL и общая
система типов CTS позволяют многим языкам
программирования, компиляторы для которых
могут генерировать код на языке MS1L,
использовать библиотеку классов .NET Framework.
Именно в этом состоит одно из наиболее
заметных различий между платформами .NET и Java,
которые в значительной степени используют
одну и ту же философию.
Дисассемблер промежуточного
языка Microsoft ILDASM (Microsoft Intermediate Language Disassembler)
может отображать метаданные и инструкции
языка MSIL, связанные с соответствующим .NET-кодом.
Дисассемблер ILDASM является очень полезной
утилитой, которая используется при отладке
приложений. Он позволяет более глубоко
понять инфраструктуру платформы .NET. Кроме
того, дисассемблер промежуточного языка
Microsoft ILDASM можно использовать для изучения
кода библиотеки классов .NET Framework [Дисассемблер
ILDASM можно найти в меню Tools (Сервис) Visual Studio.NET.
Он находится также в подкаталоге
Microsoft.NET\FrameworkSDK\Bm. Дисассемблер можно
активизировать, щелкнув два раза на его
названии в окне Проводника (Explorer) или с
помощью командной строки. Если вы
активизируете дисассемблер ILDASM с помощью
командной строки (или из среды VS.NET), то
используйте ключ /ADV для получения доступа к
некоторым его дополнительным возможностям.].
На рис. 2.1 приведен фрагмент кода на языке MSIL,
взятый из примера Serialize (Сериализация). В
данном фрагменте описывается создание двух
новых объектов Customer (Клиент) и их добавление
в список [Откройте пример Senahze.exe и щелкните
на знаке плюс (+) рядом с пунктом Test (Тестирование).
Щелкните два раза на элементе Main (Главная),
чтобы инициировать в MSIL главную процедуру.].
Инструкция newobj создает новую
объектную ссылку, используя параметр
конструктора [Формально он не является
параметром. В промежуточном языке IL
используется стек; конструктор
представляет собой лексему метаданных,
записанную в стек.]. Инструкция stloc
сохраняет значение в локальной переменной.
Инструкция Idloc загружает значение
локальной переменной [Подробно
промежуточный язык Microsoft MSIL описан в
документах Европейской Ассоциации
производителей ЭВМ (European Computer Manufacturers'
Association — ЕСМА). Особенно рекомендуется
изучить раздел "Partition III- CIL Instruction Set",
посвященный системе команд.]. Настоятельно
рекомендуем вам поэкспериментировать с
дисассемблером ILDASM и изучить его
возможности.
Рис. 2.1. Фрагмент кода из примера Serialize (Сериализация)
Так как компиляторы всех языков
программирования транслируют на один общий
промежуточный язык и используют общую
библиотеку базовых классов (Base Class Library), то
открывается возможность взаимодействия
поддерживаемых языков. Иными словами,
поддерживаемые языки могут в определенных
пределах рассматриваться как
функционально совместимые. Но поскольку
все части общей системы типов CTS
реализованы не во всех языках, не
удивительно, что один язык может обладать
свойствами, которые отсутствуют в другом.
Спецификация общего языка (Common
Language Specification — CLS) определяет подмножество
общей системы типов CTS, содержащее основные
функциональные возможности, которые должны
быть реализованы во всех .NET-языках для того,
чтобы они могли взаимодействовать друг с
другом. Именно согласно этой спецификации
класс, написанный на Visual Basic.NET, может быть
производным от класса, написанного на
управляемом C++ или С#. Следствием
использования спецификации общего языка CLS
является возможность межъязыковой отладки.
Примером соблюдения правил спецификации
общего языка CLS является то, что вызовы
методов могут не поддерживать переменное
число аргументов, хотя такая конструкция и
может быть выражена в языке MSIL.
Требование совместимости со
спецификацией общего языка CLS
предъявляется только к общедоступным
свойствам. Например, класс может содержать
приватный член, который не совместим со
спецификацией общего языка CLS, и при этом
являться базовым классом для класса,
реализованного на другом языке,
поддерживаемом платформой .NET. Например,
общедоступные (public) и защищенные (protected)
имена классов, код которых написан на языке
C++ и С#, не должны отличаться только
регистром используемых символов, поскольку
в таких языках как VB.NET регистр клавиатуры (регистр
прописных и строчных букв) не учитывается.
Но имена приватных (private) полей могут
различаться именно регистром клавиатуры (т.е.
прописными и строчными буквами).
Компанией Microsoft предлагается
несколько языков программирования,
совместимых со спецификацией общего языка
CLS: C#, Visual Basic.NET, и C++ с управляемыми
расширениями. Независимые разработчики
предлагают и другие языки программирования
(их уже больше дюжины). Компания ActiveState
занимается реализацией языков Perl и Python.
Компания Fujitsu реализует язык COBOL.
В примере Serialize (Сериализация)
второй экземпляр объекта Customer (Клиент) был
присвоен той же переменной, которой раньше
был присвоен первый экземпляр. При этом для
удаления первого экземпляра класса из
памяти деструктор не вызывался. В данном
примере ни одна из выделенных областей
памяти никогда не освобождалась. Для
освобождения памяти от объектов, которые
являются экземплярами классов, объявленных
с помощью ключевого слова _дс (сборщик
мусора), платформа .NET использует
автоматическую сборку мусора. Если память,
выделенная в управляемой динамически
распределяемой области памяти, становится
висячей или выходит из области видимости,
то она заносится в список участков памяти,
подлежащих освобождению. Периодически
система инициирует процесс сборки мусора.
Освободившаяся в результате этого память
возвращается в динамически распределяемую
область памяти.
Благодаря автоматическому
управлению памятью утечка памяти в системе
исключается. Утечка памяти является одной
из самых распространенных ошибок при
программировании на языках С и C++. В
большинстве случаев за счет использования
автоматической сборки мусора
распределение памяти в динамически
распределяемой области памяти происходит
значительно быстрее по сравнению с
классическими схемами. Обратите внимание,
что такие переменные KaKpcust и plist являются
управляемыми указателями на объекты, а не
самостоятельными объектами. Именно
вследствие этого и возможна сборка мусора.
Сборка мусора — одна из
нескольких служб, предоставляемых
общеязыковой средой выполнения CLR
программам, выполняющимся на платформе .NET [Формально
метаданные, общая система типов CTS (Common Type
System), спецификация общего языка CLS и
виртуальная система выполнения (Virtual Execution
System— VES) также являются частью общеязыковой
среды выполнения CLR. Прилагательное "общеязыковая"
означает, что среда выполнения является
общей для всех языков. Система виртуального
выполнения VES загружает и выполняет .NET-программы
и поддерживает динамическое связывание.
Обратитесь к документам, описывающим
общеязыковую инфраструктуру (Common Language
Infrastructure — CLI), а именно, к разделу "Partition I:
Concepts and Architecture", посвященному концепциям
и архитектуре. Эти документы переданы для
дальнейшего рассмотрения Европейской
Ассоциации производителей ЭВМ (European Computer
Manufacturers' Association — ЕСМА). Упомянутые
документы загружаются вместе с набором
инструментальных средств разработки
программного обеспечения .NET Framework SDK.].
Данные, участвующие в процессе
сборки мусора, инициируемом общеязыковой
средой выполнения CLR, называются
управляемыми данными. Управляемый код— это
код, который способен использовать службы,
предоставляемые общеязыковой средой
выполнения CLR. .NET-компиляторы, которые
генерируют код на языке MSIL, могут
генерировать управляемый код.
Управляемый код не удовлетворяет
требованиям типовой безопасности
автоматически. Язык C++ может послужить тому
классическим примером. Чтобы класс
участвовал в сборке мусора (т.е. был
управляемым), при его объявлении следует
использовать атрибут _дс (сборщик мусора).
Компилятор для C++ запрещает в таких классах
использовать арифметические операции над
указателями. Тем не менее, код на C++ не может
быть надежно проверен на типовую
безопасность, поскольку используются
библиотеки на С и C++.
Проверка кода на типовую
безопасность происходит перед его
компиляцией. Такая проверка является
необязательной и может быть пропущена, если
код аттестован. Одно из самых существенных
отличий проверяемого кода от
непроверяемого состоит в том, что в
проверяемом коде не могут использоваться
указатели. Код, в котором используются
указатели, может разрушить общую систему
типов CTS и в результате его трансляции может
получиться код, не удовлетворяющий типовой
безопасности.
Код, который удовлетворяет
типовой безопасности, не может быть легко
разрушен. Например, перезапись буфера не
может повредить другие структуры данных
или программы. К коду, удовлетворяющему
требованиям типовой безопасности, можно
применить политику безопасности [Более
подробно этот вопрос обсуждается в главе 13
"Зашита".]. Например, можно разрешить
или запретить доступ к некоторым файлам,
или элементам пользовательского
интерфейса. Вы можете предотвратить
выполнение кода, полученного из
неизвестных вам источников. Чтобы
предотвратить разрушение системы
безопасности платформы .NET, вы можете
запретить доступ к неуправляемому коду.
Благодаря типовой безопасности можно также
изолировать выполняемые ветви кода .NET друг
от друга [Области приложений (Application Domains)
обсуждаются в главе 8 "Классы каркаса .NET
Framework".].
Еще одной функцией общеязыковой
среды выполнения CLR является загрузка и
запуск .NET-программ. .NET-программы
разворачиваются в виде одной или
нескольких сборок. Сборкой является один
или несколько исполняемых файлов или
файлов динамически подключаемых библиотек
(DLL) вместе со связанными с ними метаданными.
Метаданные, которые описывают всю сборку
целиком, хранятся в декларации (манифесте)
сборки. Декларация сборки, или манифест
сборки содержит, например, список сборок, от
которых зависит данная сборка.
В нашем примере Serialize (Сериализация)
сборка содержит всего лишь один файл, Serialize .
ехе. Этот файл включает и метаданные, и код.
Поскольку декларация хранится в самой
сборке, а не в отдельном файле (как это имеет
место для библиотеки типов или системного
реестра), она всегда синхронизирована с
этой сборкой. На рис. 2.2 представлены
метаданные декларации сборки,
соответствующей данному примеру [В
дисассемблере откройте файл Serialize . ехе и
затем щелкните дважды на элементе MANIFEST.].
Обратите внимание на операторы assembly extern.
Они указывают, что данная сборка зависит от
сборок библиотеки .NET Framework, которые имеют
название mscorlib и System.Runtime.Serialization.Formatters.SOAP (Система.Время
выполнения.Преобразование в
последовательную форму.Форматеры.ЗОАР). С
помощью оператора assembly extern указываются
также версии сборок, от которых зависит наш
пример Serialize.exe.
Могут существовать несколько
версий одной сборки, причем номер версии
является частью имени сборки. Если
необходимо использовать уникальное имя
сборки, вы можете использовать открытый/индивидуальный
ключ шифрования, для того чтобы
сгенерировать уникальное (строгое) имя.
Сборки могут быть развернуты
приватно (privately) либо публично (publicly). В
случае приватного (privately) развертывания, все
необходимые приложению сборки копируются в
тот же каталог, в котором находится само
приложение. Как мы уже знаем, версия сборки
является частью ее имени. Следовательно,
несколько версий сборки могут быть
развернуты в одном или в разных каталогах и
при этом мешать друг другу они не будут. "Проклятие
(ад) динамически подключаемых библиотек (DLL)"
больше не действует.
Если сборка должна быть
общедоступна для совместного
использования, в глобальном кэше сборок (Global
Assembly Cache — GAC) делается соответствующая
запись, позволяющая другим сборкам
отыскать ее. Для сборок, при разворачивании
которых применяется глобальный кэш сборок
GAC, необходимо использовать строгие имена [Более
детально это обсуждается в главе 7 "Сборки
и развертывание".]. Возможность
развертывания сборок, а также
функциональная совместимость языков
программирования позволяют создавать
компоненты почти автоматически.
Рис. 2.2. Декларации сборки Serialize (Сериализация)
Перед выполнением на конкретной
машине, код на промежуточном языке Microsoft—
MS1L (Microsoft Intermediate Language) транслируется
оперативным компилятором, или ЛТ-компилятором
(JIT — "just-in-time" или "как раз вовремя")
в собственный (внутренний) код. Во время
работы программы некоторые участки кода
выполняться никогда не будут.
Следовательно, более эффективной может
оказаться трансляция кода из
промежуточного языка MSIL в собственный (внутренний)
код, осуществляемая по мере необходимости в
процессе выполнения приложения.
Собственный (внутренний) код при этом
сохраняется с целью повторного его
использования.
После загрузки типа, к каждому его
методу загрузчик присоединяет заглушку.
При первом вызове заглушка передает
управление ЛТ-компилятору, который
генерирует собственный (внутренний) код и
сохраняет адрес оттранслированного
собственного (внутреннего) кода в заглушке.
При последующих вызовах метода управление
передается непосредственно собственному (внутреннему)
коду.
Возможно, вам понравилась
предложенная модель безопасности и
простота использования управляемого кода,
но вас волнует вопрос о производительности
приложений. В то время, когда появились
высокоуровневые языки программирования,
программистов, пишущих приложения на самых
примитивных языках ассемблера, волновал
этот же вопрос.
Общеязыковая среда выполнения CLR
разрабатывалась с прицелом на высокую
производительность приложений. Ведь только
при первом вызове метода общеязыковая
среда выполнения CLR осуществляет проверку
правильности и затем выполняет оперативную
компиляцию в собственный (внутренний) код, в
который встроены средства безопасности,
например проверка границ массивов. Когда
метод вызывается в следующий раз,
непосредственно выполняется собственный (внутренний)
код. Схема управления памятью
спроектирована так, чтобы достичь высокой
производительности. Распределение памяти
происходит почти мгновенно, при этом из
управляемой динамически распределяемой
области памяти берется следующий доступный
участок. Освобождение памяти выполняется
сборщиком мусора, который реализован на
основе эффективного алгоритма.
За все это вы расплачиваетесь
тогда, когда при проверке безопасности
приходится просматривать стек.
При создании Web-страниц
используется компилируемый, а не
интерпретируемый код. В результате, ASP.NET-приложения
работают намного быстрее, чем ASP-приложения.
В 95 процентах кода надежность и
легкость его создания с лихвой
компенсирует незначительные потери в
производительности. При создании
высокопроизводительных серверных
приложений также могут использоваться
такие технологии как библиотека ATL Server или
неуправляемый C++.